package com.scs.application.config;

import com.alibaba.fastjson.parser.ParserConfig;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.std.DateDeserializers;
import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;
import com.scs.application.core.global.GlobalDictService;
import com.scs.application.core.jackson.CustomDateFormat;
import com.scs.application.core.mvc.filter.RequestWrapperFilter;
import com.scs.application.core.serial.SerialUtils;
import com.scs.application.core.utils.*;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

import java.io.IOException;
import java.util.Date;

/**
 * @Description:
 */
@Configuration
public class CoreBeanConfiguration implements InitializingBean {

    @Bean
    public SpringHolder springHolder() {
        return new SpringHolder();
    }

    @Bean
    public RequestWrapperFilter requestWrapperFilter() {
        return new RequestWrapperFilter();
    }

    @Bean
    public ObjectMapper objectMapper() {
//        ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().build();


        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

        // 忽略json字符串中不识别的属性
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 忽略无法转换的对象 “No serializer found for class com.xxx.xxx”
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        // NULL不参与序列化
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        // PrettyPrinter 格式化输出
        objectMapper.configure(SerializationFeature.INDENT_OUTPUT, false);

        // 指定时区，默认 UTC，而不是 jvm 默认时区
        // objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
        // 日期类型处理
        // objectMapper.setDateFormat(new SimpleDateFormat(DateUtils.DEFAULT_PATTER));
        CustomDateFormat customDateFormat = new CustomDateFormat();
        objectMapper.setDateFormat(customDateFormat);

        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Date.class, new DateSerializer().withFormat(false, customDateFormat));

        /**
         * {@link com.fasterxml.jackson.databind.deser.BasicDeserializerFactory#createBeanDeserializer(DeserializationContext, JavaType, BeanDescription)}
         * {@link com.fasterxml.jackson.databind.deser.BasicDeserializerFactory#findDefaultDeserializer(DeserializationContext, JavaType, BeanDescription)}
         * {@link DateDeserializers.DateDeserializer}
         */
        simpleModule.addDeserializer(Date.class, new DateDeserializers.DateDeserializer() {
            @Override
            public java.util.Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                if (p.hasToken(JsonToken.VALUE_STRING)) {
                    String str = p.getText().trim();
                    if (str.length() == 0) {
                        return (Date) getEmptyValue(ctxt);
                    }
                    try {
                        return DateUtils.parse(str);
                    } catch (Exception e) {
                        return (java.util.Date) ctxt.handleWeirdStringValue(handledType(), str,
                                "expected format \"%s\"", _formatString);
                    }
                }
                return (Date) getEmptyValue(ctxt);
            }
        });
        simpleModule.addDeserializer(String.class, new StdScalarDeserializer<String>(String.class) {
            @Override
            public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                boolean hasToken = p.hasToken(JsonToken.VALUE_STRING)
                        || p.hasToken(JsonToken.VALUE_NUMBER_INT)
                        || p.hasToken(JsonToken.VALUE_NUMBER_FLOAT);
                return hasToken ? StringUtils.trim(p.getValueAsString()) : null;
            }
        });
        objectMapper.registerModule(simpleModule);

        return objectMapper;
    }

    @Bean
    @Order(0)
    public SpringUtils springUtils() {
        return new SpringUtils();
    }

    @Bean
    @Order(1)
    public CacheUtils cacheUtils() {
        return new CacheUtils();
    }

    @Bean
    public GlobalDictService dictService() {
        return new GlobalDictService();
    }

    @Bean
    @Order(2)
    public SerialUtils serialUtils() {
        return new SerialUtils();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        /**
         * resolved autotype is not support, link: https://github.com/alibaba/fastjson/wiki/enable_autotype
         */
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
    }


}
